//
//  MHDiskCacheTool.m
//  cacheTool
//
//  Created by 牟华 on 16/10/27.
//  Copyright © 2016年 牟华. All rights reserved.
//

#import "MHDiskCacheTool.h"

NSString * const kMHCacheContent = @"kMHCacheContent";
NSString * const kMHObjectCache = @"kMHObjectCache";
NSString * const kMHImageCache = @"kMHImageCache";
NSString * const kMHOtherDataCache = @"kMHOtherDataCache";

NSString * const kMHDefaultCacheName = @"kMH_DEFAULT_CACHE";
NSString * const kMHCachePrex = @"COM_MH_DISK_CACHE";
NSString * const kMHIOQueueName = @"COM_MH_DISK_CACHE_IOQUEUE";

@interface MHDiskCacheTool ()

@property (strong, nonatomic) NSFileManager *fileManager;
@property (strong, nonatomic) dispatch_queue_t ioQueue;
@property (strong, nonatomic) NSString *diskCachePath;
@property (strong, nonatomic) NSString *cacheType;

@end


@implementation MHDiskCacheTool

- (instancetype)initWithType:(NSString *)cacheType
{
    self = [super init];
    if (self) {
        __weak typeof(self) selfWeak = self;
        self.cacheType = cacheType;
        
        NSString *cacheName = [NSString stringWithFormat:@"%@/%@%@", kMHCacheContent, kMHCachePrex, cacheType];
        NSString *ioName = [NSString stringWithFormat:@"%@%@", kMHIOQueueName, cacheType];
        
        self.ioQueue = dispatch_queue_create([ioName UTF8String], DISPATCH_QUEUE_SERIAL);
        NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true).firstObject;
        self.diskCachePath = [path stringByAppendingPathComponent:cacheName];
        
        //先创建好对象的文件夹
        dispatch_sync(self.ioQueue, ^{
            selfWeak.fileManager = [NSFileManager defaultManager];
            [selfWeak.fileManager createDirectoryAtPath:selfWeak.diskCachePath withIntermediateDirectories:true attributes:nil error:nil];
        });
    }
    return self;
}

#pragma mark - 公有方法public method
- (void)cacheWithKey:(NSString *)key value:(id)value image:(UIImage *)image data:(NSData *)otherData completeHandler:(saveCompleteHandler)completeHandler
{
    NSString *path = [self.diskCachePath stringByAppendingPathComponent:key];
    
    if ([self.cacheType isEqualToString:kMHObjectCache]) {
        [self cacheObjectWithKey:key value:value path:path completeHandler:completeHandler];
    } else if ([self.cacheType isEqualToString:kMHImageCache]) {
        [self cacheImageWithKey:key image:image path:path completeHandler:completeHandler];
    } else if ([self.cacheType isEqualToString:kMHOtherDataCache]) {
        [self cacheOtherDataWithKey:key data:otherData path:path completeHandler:completeHandler];
    }
}

-(void)getWithKey:(NSString *)key objectGetHandler:(void(^)(id value))completeObj imageGetHandler:(void(^)(UIImage *image))completeImage otherDataGetHandler:(void(^)(NSData *data))completeOtherData
{
    NSString *path = [self.diskCachePath stringByAppendingPathComponent:key];
    
    if ([self.cacheType isEqualToString:kMHObjectCache]) {
        [self getObjectWithKey:key path:path getComplete:completeObj];
    } else if ([self.cacheType isEqualToString:kMHImageCache]) {
        [self getImageWithKey:key path:path getComplete:completeImage];
    } else if ([self.cacheType isEqualToString:kMHOtherDataCache]) {
        [self getOtherDataWithKey:key path:path getComplete:completeOtherData];
    }
}

#pragma mark - 私有方法private method
#pragma mark - 实例化存储文件类型
+ (instancetype)sharedCacheObj
{
    return [[self alloc] initWithType:kMHObjectCache];
}

+ (instancetype)sharedCacheImage
{
    return [[self alloc] initWithType:kMHImageCache];
}

+ (instancetype)sharedCacheOtherData
{
    return [[self alloc] initWithType:kMHOtherDataCache];
}

#pragma mark - 缓存对象
- (void)cacheObjectWithKey:(NSString *)key value:(id)value path:(NSString *)path completeHandler:(saveCompleteHandler)complete
{
    dispatch_async(self.ioQueue, ^{
        // object归档存储
        NSMutableData *dataM = [NSMutableData data];
        NSKeyedArchiver *keyArchiver =  [[NSKeyedArchiver alloc] initForWritingWithMutableData:dataM];
        [keyArchiver encodeObject:value forKey:key];
        
        [keyArchiver finishEncoding];
        if (dataM != nil) {
            [dataM writeToFile:path options:NSDataWritingAtomic error:nil];
            if (complete) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    complete();
                });
            }
        }
    });
}

#pragma mark - 缓存图片
- (void)cacheImageWithKey:(NSString *)key image:(UIImage *)image path:(NSString *)path completeHandler:(saveCompleteHandler)complete
{
    dispatch_async(self.ioQueue, ^{
        NSData *imgData = UIImagePNGRepresentation(image);
        
        if (image != nil) {
            [imgData writeToFile:path options:NSDataWritingAtomic error:nil];
            if (complete) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    complete();
                });
            }
        }
    });
}

#pragma mark - 缓存其他data
- (void)cacheOtherDataWithKey:(NSString *)key data:(NSData *)data path:(NSString *)path completeHandler:(saveCompleteHandler)complete
{
    dispatch_async(self.ioQueue, ^{
        
        if (data != nil) {
            [data writeToFile:path options:NSDataWritingAtomic error:nil];
            if (complete) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    complete();
                });
            }
        }
    });
}

#pragma mark - 获取对象
- (void)getObjectWithKey:(NSString *)key path:(NSString *)path getComplete:(void(^)(id value))completeObj
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if ([self.fileManager fileExistsAtPath:path]) {
            NSData *mData = [NSData dataWithContentsOfFile:path];
            NSKeyedUnarchiver *unKeyedArchieve = [[NSKeyedUnarchiver alloc] initForReadingWithData:mData];
            id getobj = [unKeyedArchieve decodeObjectForKey:key];
            if (completeObj) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    completeObj(getobj);
                });
                
            }
        }
    });
    
}

#pragma mark - 获取图片
- (void)getImageWithKey:(NSString *)key path:(NSString *)path getComplete:(void(^)(UIImage *image))completeImage
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if ([self.fileManager fileExistsAtPath:path]) {
            NSData *mData = [NSData dataWithContentsOfFile:path];
            UIImage *getImage = [UIImage imageWithData:mData];
            if (getImage) {
                if (completeImage) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        completeImage(getImage);
                    });
                    
                }
            }
        }
    });
}


#pragma mark - 获取其他data
- (void)getOtherDataWithKey:(NSString *)key path:(NSString *)path getComplete:(void(^)(NSData *data))completeData
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if ([self.fileManager fileExistsAtPath:path]) {
            NSData *mData = [NSData dataWithContentsOfFile:path];
            if (mData) {
                if (completeData) {
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        completeData(mData);
                    });
                }
            }
        }
    });
}

+ (void)clearDisk
{
    NSString *cacheName = [NSString stringWithFormat:@"%@/", kMHCacheContent];
    
    NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true).firstObject;
    NSString *itemsPath = [path stringByAppendingPathComponent:cacheName];
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    [fileMgr removeItemAtPath:itemsPath error:nil];
}

@end
